const path = require("path");
const webpack = require("webpack");
// 将css代码提取为独立文件的插件
const miniCssExtractPlugin = require("mini-css-extract-plugin");
// css模块资源优化插件 压缩css文件
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
// 每次运行打包时清理过期文件
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
// 用于生成html文件的插件
const HtmlWebpackPlugin = require("html-webpack-plugin");
// 去掉控制台打印信息 压缩js
const TerserPlugin = require("terser-webpack-plugin");
// 消除未使用的CSS
// 引入glob，因为我们需要同步检查html模板
// const glob = require("glob-all");
// const PruifyCSSPlugin = require("purifycss-webpack");
const chalk = require("chalk"); // 改变命令行中输出日志颜色插件
// antd 暗色主题
const darkTheme = require("@ant-design/dark-theme").default;
// 判断node运行环境
const isDev = process.env.NODE_ENV === "development";

// To find which plugin(s) is causing the warning, put this on the top of your webpack config file
// process.traceDeprecation = true;
// do not entirely suppress deprecation warnings like this one (NOT RECOMMENDED)
process.noDeprecation = true;

const config = {
  mode: isDev ? "development" : "production", // production development none
  entry: path.resolve(__dirname, `src/index.js`), // ['',''] {a:'',b:['','']}
  // entry: entries, // ['',''] {a:'',b:['','']}
  // target: "node",
  output: {
    filename: "js/[name].[hash:8].bundle.js", // [name].js [chunkhash].js
    path: path.resolve(__dirname, "build") // 必须是绝对路径
    // publicPath 是生成的js,css,images等静态资源的引用路径的基本路径
    // publicPath: "./" //'/assets/' "https://cdn.example.com/"
    // library: "MyLibrary",// 导出库(exported library)的名称
    // libraryTarget: "umd", // 通用模块定义
  },
  module: {
    rules: [
      {
        test: /\.(png|svg|jpg|gif|jpeg|tif)$/,
        use: [
          // {
          // webpack通过file-loader处理资源文件，它会将rules规则命中的资源文件按照配置的信息（路径，名称等）输出到指定目录，
          // 并返回其资源定位地址（输出路径，用于生产环境的publicPath路径），默认的输出名是以原文件内容计算的MD5 Hash命名的
          //   loader: "file-loader",
          //   options: {
          //       outputPath: "images/"
          //   }
          // },
          {
            // 构建工具通过url-loader来优化项目中对于资源的引用路径，并设定大小限制，当资源的体积小于limit时将其直接进行Base64转换后嵌入引用文件，体积大于limit时可通过fallback参数指定的loader进行处理。
            // 打包后可以看到小于8k的资源被直接内嵌进了CSS文件而没有生成独立的资源文件
            loader: "url-loader",
            options: {
              limit: 8129, //小于limit限制的图片将转为base64嵌入引用位置
              fallback: "file-loader", //大于limit限制的将转交给指定的loader处理，开启这里后就无需再单独配置file-loader
              name: "[name].[ext]",
              outputPath: "images", //options会直接传给fallback指定的loader
              publicPath: isDev ? "/images" : "../images"
            }
          }
        ]
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [
          {
            loader: "file-loader",
            options: {
              outputPath: "css/fonts",
              publicPath: "fonts",
              name: "[name].[hash:8].[ext]"
            }
          }
        ]
      },
      {
        test: /\.(csv|tsv)$/,
        use: ["csv-loader"]
      },
      {
        test: /\.xml$/,
        use: ["xml-loader"]
      },
      {
        test: /\.css$/,
        include: [path.resolve(__dirname, "src")], // 限制打包范围，提高打包速度
        exclude: /node_modules/, // 排除node_modules文件夹
        use: [
          // {    // 当配置MinCssExtractPlugin.loader后，此项就无需配置，原因看各自作用
          //     loader: "style-loader"  // 将处理结束的css代码存储在js中，运行时嵌入`<style>`后挂载到html页面上
          // },
          {
            // 将处理后的CSS代码提取为独立的CSS文件，可以只在生产环境中配置，但我喜欢保持开发环境与生产环境尽量一致
            loader: miniCssExtractPlugin.loader
          },
          {
            // CSS加载器，使webpack可以识别css文件
            loader: "css-loader",
            options: {
              sourceMap: isDev
            }
          },
          {
            //承载autoprefixer功能，为css添加前缀
            loader: "postcss-loader",
            options: {
              sourceMap: isDev
            }
          }
        ]
      },
      {
        test: /\.scss$/,
        include: [path.resolve(__dirname, "src")], // 限制打包范围，提高打包速度
        exclude: /node_modules/, // 排除node_modules文件夹
        use: [
          // {    // 当配置MinCssExtractPlugin.loader后，此项就无需配置，原因看各自作用
          //     loader: "style-loader"  // 将处理结束的css代码存储在js中，运行时嵌入`<style>`后挂载到html页面上
          // },
          {
            // 将处理后的CSS代码提取为独立的CSS文件，可以只在生产环境中配置，但我喜欢保持开发环境与生产环境尽量一致
            loader: miniCssExtractPlugin.loader
          },
          {
            // CSS加载器，使webpack可以识别css文件
            loader: "css-loader",
            options: {
              sourceMap: isDev
            }
          },
          {
            //承载autoprefixer功能，为css添加前缀 postcss一定要写在scss-loader之前
            loader: "postcss-loader",
            options: {
              parser: "postcss-scss",
              sourceMap: isDev
            }
          },
          {
            // 编译sass，webpack默认使用node-sass进行编译，所以需要同时安装 sass-loader 和 node-sass
            loader: "sass-loader",
            options: {
              // loader 的额外参数，配置视具体 loader 而定
              sourceMap: isDev // 要安装resolve-url-loader，当此配置项启用 sourceMap 才能正确加载 Sass 里的相对路径资源，类似background: url(../image/test.png)
            }
          }
        ]
      },
      {
        test: /\.less$/,
        // include: [path.resolve(__dirname, "src")], // 限制打包范围，提高打包速度
        // exclude: /node_modules/, // 排除node_modules文件夹 为了antd的样式加载，注释这行
        use: [
          // {    // 当配置MinCssExtractPlugin.loader后，此项就无需配置，原因看各自作用
          //     loader: "style-loader"  // 将处理结束的css代码存储在js中，运行时嵌入`<style>`后挂载到html页面上
          // },
          {
            // 将处理后的CSS代码提取为独立的CSS文件，可以只在生产环境中配置，但我喜欢保持开发环境与生产环境尽量一致
            loader: miniCssExtractPlugin.loader
          },
          {
            // CSS加载器，使webpack可以识别css文件 translates CSS into CommonJS
            loader: "css-loader",
            options: {
              // 不处理引入图片的路径问题
              url: false,
              sourceMap: isDev,
              importLoaders: 1
            }
          },
          {
            //承载autoprefixer功能，为css添加前缀 浏览器css前缀
            // 这里的postcss必须放在less-loader前面，否则引入antd的时候，会报错
            loader: "postcss-loader",
            options: { parser: "postcss-less", sourceMap: isDev }
          },
          {
            // 编译less，webpack默认使用less进行编译，所以需要同时安装 less-loader 和 less compiles Less to CSS
            loader: "less-loader",
            options: {
              javascriptEnabled: true,
              sourceMap: isDev,
              modifyVars: darkTheme
            }
          }
        ]
      },
      {
        test: /\.js|jsx$/,
        use: "babel-loader",
        include: /src/, // 只转化src目录下的js
        exclude: /node_modules/ // 排除掉node_modules，优化打包速度
      }
    ]
  },
  plugins: [
    // 生成html文件
    // ...pages,
    new HtmlWebpackPlugin({
      title: "aliyun-oss-log-analysis",
      filename: "index.html",
      template: "src/index.html",
      chunks: ["main", "common", "vendors", "manifest"]
    }),
    // 第三方库的公共引入 暴露全局 不用单独import
    new webpack.ProvidePlugin({
      React: "react"
    }),
    // 打包css sass less
    new miniCssExtractPlugin({
      filename: "css/[name].[hash:8].css"
    })
    // 每次打包，清理过期文件 与antd的样式按需引入冲突
    // new CleanWebpackPlugin(),
    // 消除无用多余的css
    // new PruifyCSSPlugin({
    //   // paths: glob.sync(path.join(__dirname, "src/*.html")) //src下所有的html
    //   paths: glob.sync([
    //     path.join(__dirname, "./src/**/*.js"),
    //     path.join(__dirname, "./node_modules/antd/es/**/*.js")
    //   ])
    // })
  ],
  // 提取公共模块，包括第三方库和自定义工具库等
  optimization: {
    // 找到chunk中共享的模块,取出来生成单独的chunk
    splitChunks: {
      chunks: "all", // async表示抽取异步模块，all表示对所有模块生效，initial表示对同步模块生效
      cacheGroups: {
        vendors: {
          // 抽离第三方插件
          test: /[\\/]node_modules[\\/]/, // 指定是node_modules下的第三方包
          name: "vendors",
          priority: -10 // 抽取优先级
        },
        commons: {
          // 抽离自定义工具库
          name: "common",
          priority: -20, // 抽取优先级
          minChunks: 2, // 表示将引用模块如不同文件引用了多少次，才能分离生成新chunk
          minSize: 0 // 将引用模块分离成新代码文件的最小体积
        }
      }
    },
    // 代码压缩 mode='production'时生效
    minimizer: [
      // 对生成的CSS文件进行压缩
      new OptimizeCssAssetsWebpackPlugin({
        cssProcessorPluginOptions: {
          // options 去掉注释
          preset: ["default", { discardComments: { removeAll: true } }]
        }
      }),
      // 压缩js
      new TerserPlugin({
        minify: (file, sourceMap) => {
          // https://github.com/mishoo/UglifyJS2#minify-options
          const uglifyJsOptions = {
            /* your `uglify-js` package options */
            output: {
              // 去掉注释
              comments: false
            },
            compress: {
              // 去掉控制台打印
              drop_debugger: true,
              drop_console: true
            }
          };

          if (sourceMap) {
            uglifyJsOptions.sourceMap = {
              content: sourceMap
            };
          }

          return require("uglify-js").minify(file, uglifyJsOptions);
        }
      })
    ],
    // 为 webpack 运行时代码创建单独的chunk
    runtimeChunk: {
      name: "manifest"
    }
  }
  // 配置webpack执行相关
  // performance: {
  //   maxEntrypointSize: 1000000, // 最大入口文件大小1M
  //   maxAssetSize: 1000000 // 最大资源文件大小1M
  // }
};

if (isDev) {
  config.devtool = "inline-source-map";
  config.devServer = {
    contentBase: path.resolve(__dirname, "build"),
    historyApiFallback: true,
    // host: ip,
    port: 3000,
    // progress: true,
    overlay: true,
    // open: true,
    hot: true,
    noInfo: true,
    after() {
      // eslint-disable-next-line no-console
      console.log(chalk.cyan(`http://localhost:${this.port} 已成功打开`));
    }
  };
} else {
  config.plugins.push(new CleanWebpackPlugin());
  config.output.publicPath = "./";
}

module.exports = config;
